<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ts 类中泛型 难点 </title>
</head>
<body>    
</body>
</html>
<script>
    //2021-05-19 修订 

    //demo代码如下 编写一个基本的类SelectGirl
    //在类的构造函数中(constructor)需传递一组女孩的名称 然后再通过下边展示女孩名字 
    class SelectGirl{
        constructor(private girls: string[]){}

        getGirl(index:number):string{
            return this.girls[index];
        }

    }
    const selectGirl = new SelectGirl(["大长腿","大胸","齐肩发"]);
    console.log(selectGirl.getGirl(1));  
    // ts-node demo.ts 预览一下         //大胸 


    //需求 不通过名字通过编号找女孩 即使用泛型  看代码  
    class SelectGirl{
        constructor(provide girls:string[] | number[]){}

        getGirl(index:number):string | number{
            return this.girls[index];
        }

    } 
    //初始类的泛型  
    //使用泛型重构代码  <>编写 代码如下  
    class SelectGirl<T>{
        constructor(provide girls: T[]){
            getGirl(index:number):T{
                return this.girls[index]
            }
        }
    }
    const selectGirl = new SelectGirl(["大长腿","大胸","齐肩发"])
    console.log(selectGirl.getGirl(1));
    //这时候代码并不报错 同时使用了泛型 
    
    //注意 ts通过类型推论出来的 这个少用 
    //所以还是需要再实例化对象的时候 对泛型的值进行确定 比如string类型 代码如下 
    const selectGirl = new SelectGirl() <string>["大美","二美","三美"];


//泛型中的继承 
    //需求又变了 要求返回一个对象的name 代码如下(按需抛出)
    return this.girls[index].name;
    //即传递过来的值必须是一个对象类型的 里面带有name属性 
    //这时候考虑用继承 接口方式来实现 写一个Girl的接口 每个接口都要有name属性 代码如下 
    interface Girl{
        name:string;
    }  
    //有了接口后用extends 关键字实现泛型继承 代码如下  
    class SelectGirl <T extends Girl>{

    }
    //代码即 泛型里面必须有一个name属性 因为它继承了Girl接口 
    //至此代码还报错 因为getGirl方法返回值类型不对 这时候应该是一个string类型才对 
    //正确代码如下 
    interface Girl{
        name:string;
    }                  //这是按需抛出的 接口
    class SelectGirl<T extends Girl>{
        constructor(provide girls: T[]){}
        getGirl(index:number):string{
            return this.girls[index].name
        }
    }    
    const selectGirl = new SelectGirl([
        {name:"大美"},{name:"二美"},{name:"三美"}
    ]);
    console.log(selectGirl.getGirl(1));
    //回头看  我在SelectGirl类中使用了泛型  
    //即不知道以后用什么类型 但是有一个约束条件 (这个类型 必须要有一个name属性 )
 

//泛型约束  
    //现在的泛型约束可以是任意类型 对象 字符串 布尔 数字  
    // 需求 这个泛型必须是 string 或者 number 还拿上面的demo 代码还原最初样子 
    class SelectGirl<T> {
    constructor(private girls: T[]) {}
    getGirl(index: number): T {
        return this.girls[index];
    }
    }
    const selectGirl = new SelectGirl<string>(["大脚", "刘英", "晓红"]);
    console.log(selectGirl.getGirl(1));
    //然后 进行约束 使用关键字extends来进行约束 代码如下
    class SelectGirl<T extends number|string>{//......}    

    //end 注意实际工作中 泛型的应用更加的广泛和复杂 需要在实际的项目中不断加深理解

























































             




















</script>